package rbac.service.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import rbac.dao.RoleDao;
import rbac.dao.UserDao;
import rbac.dao.UserGroupDao;
import rbac.entity.RbacRole;
import rbac.entity.RbacUser;
import rbac.entity.RbacUserGroup;
import rbac.enums.EntityDoNotExistExceptionMessage;
import rbac.exception.EntityDoNotExistException;
import rbac.service.UserGroupService;


/**
 * RBAC 用户组管理 service 实现类.
 * 
 * @author Huadi
 * @author Zoufengyang
 */
@Service("userGroupService")
public class UserGroupServiceImpl implements UserGroupService {

	@Autowired
	@Qualifier("userGroupDao")
	private UserGroupDao userGroupDao;

	@Autowired
	@Qualifier("roleDao")
	private RoleDao roleDao;

	@Autowired
	@Qualifier("userDao")
	private UserDao userDao;

	@Override
	public RbacUserGroup getUserGroup(Integer id) {
		return userGroupDao.getUserGroup(id);
	}

	@Override
	public List<RbacUserGroup> getAllUserGroups() {
		return userGroupDao.getAllUserGroups();
	}

	@Override
	public void save(RbacUserGroup userGroup) {
		userGroupDao.save(userGroup);
	}

	@Override
	public void update(RbacUserGroup userGroup)
			throws EntityDoNotExistException {
		if (null != userGroupDao.getUserGroup(userGroup.getId())) {
			userGroupDao.update(userGroup);
		} else {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}
	}

	@Override
	public void delete(RbacUserGroup userGroup) {
		userGroupDao.delete(userGroup);
	}

	@Override
	public void delete(Integer id) {
		userGroupDao.delete(id);
	}

	@Override
	public void grantRoleToUserGroup(RbacRole role, RbacUserGroup userGroup)
			throws EntityDoNotExistException {
		if (!userGroup.getRoles().contains(role)) {
			userGroup.getRoles().add(role);
			this.update(userGroup);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor={Exception.class})
	public void grantRoleToUserGroup(Integer roleId, Integer userGroupId)
			throws EntityDoNotExistException {
		RbacRole role = roleDao.getRole(roleId);
		if (null == role) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.RoleDoNotExist);
		}
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}

		this.grantRoleToUserGroup(role, userGroup);
	}

	@Override
	public void revokeRoleFromUserGroup(RbacRole role, RbacUserGroup userGroup)
			throws EntityDoNotExistException {
		if (userGroup.getRoles().remove(role)) {
			this.update(userGroup);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor={Exception.class})
	public void revokeRoleFromUserGroup(Integer roleId, Integer userGroupId)
			throws EntityDoNotExistException {
		RbacRole role = roleDao.getRole(roleId);
		if (null == role) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.RoleDoNotExist);
		}
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}

		this.revokeRoleFromUserGroup(role, userGroup);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor={Exception.class})
	public void grantRoleToUserGroup(Integer userGroupId,
			List<Integer> selectedRoles) throws EntityDoNotExistException {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		Set<RbacRole> roleSet = new HashSet<RbacRole>();
		for (Integer roleId : selectedRoles) {
			RbacRole r = roleDao.getRole(roleId);
			if (null != r) {
				roleSet.add(r);
			}
		}
		userGroup.setRoles(roleSet);
		this.update(userGroup);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor={Exception.class})
	public void addUsersToUserGroup(Collection<Integer> userIds,
			Integer userGroupId) {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		List<RbacUser> users = userDao.getUsers(userIds); // 获取要添加进该用户组的用户.
		Set<RbacUser> originalUsers = userGroup.getUsersBelongsTo();
		originalUsers.removeAll(users); // 获取从该用户组删除的用户.

		for (RbacUser user : users) {
			user.getUserGroups().add(userGroup);
		}
		for (RbacUser user : originalUsers) {
			user.getUserGroups().remove(userGroup);
		}
		for (RbacUser user : users) {
			userDao.update(user);
		}
		for (RbacUser user : originalUsers) {
			userDao.update(user);
		}
	}
}
